#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <stdarg.h>
#include <dlfcn.h>

#include "port.h"
#include "UPI_OS.h"
#include "android/log.h"
#include "filterapi.h"
#include "spts.h"
#include "sas.h"
#include "cas.h"
#include "dec_api.h"

//#define SAVEDIR 	"/data/data/com.smit.livevideo"
//#define SAVEFILE  	"/data/data/com.smit.livevideo/FLASH4M.hex"

#define LOG_TAG "DVB-CORE"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO  , LOG_TAG, __VA_ARGS__)
#define FILTER_MAX_NUM     (64)
static unsigned int m_frequency;
static unsigned char m_bandwidth;
dvb_handle_t m_mutex;
dvb_handle_t m_tunerMutex;
pfDvbInitDoneCb pfPlatformInitCb = NULL;
int g_hPlay = 0;

char savedir[100]={0};
char savefile[100]={0};

typedef struct
{
	filter_handle_t 	m_hFilter;
	dvb_handle_t		m_hQueueID;
	pfDmxDataGotCb	m_pfCallback;
}mwFilter_t;

static mwFilter_t s_ahFilter[40];

static int DVB_Filter_DataCallBack(void *pCallbackData)
{
	return TRUE;
}

void SasSessionConnected(int status)
{
	if(pfPlatformInitCb)
		pfPlatformInitCb(status);
}

void mwPlatformInit(pfDvbInitDoneCb callback,char *appFilesDir)
{
	unsigned int i;

	strcat(savedir,appFilesDir);
	strcat(savefile,appFilesDir);
	strcat(savefile,"/FLASH4M.hex");
	
	m_mutex = mwOsMutexCreate("mwPortMutex");
	m_tunerMutex = mwOsMutexCreate("mwTunerMutex");
	for(i=0; i<sizeof(s_ahFilter)/sizeof(s_ahFilter[0]); i++)
	{
		s_ahFilter[i].m_hFilter = INVALID_FILTER_HANDLE;
	}
	
	Filter_Init();
	SPTS_Init();
	pfPlatformInitCb = callback;
	SasRegisterSasConnectedNotify(SasSessionConnected);
}

int mwPlatformTerm()
{
	int ret;
	return ret;
}

static pfDebugOutput pfDebug = NULL;
void mwRegistorDebugFunction(pfDebugOutput pfDebugFun)
{
	pfDebug = pfDebugFun;
}

void mwDebug(char *format, ...)
{
	char			szBuffer[4096];
	va_list			va;
	int len;

	va_start(va, format);

	// limit the written size and reserve one byte for NULL character
	len = vsnprintf(szBuffer, sizeof(szBuffer) - 1, format, va);
	va_end(va);

	if (-1 == len)
	{
		// the string is truncated because of lacking memory
		len = sizeof(szBuffer) -1;
	}
	szBuffer[len] = '\0';

	if(pfDebug)
		pfDebug(MW_DEBUG_COMMON, szBuffer);
}
void mwError(char *format, ...)
{	
	char			szBuffer[4096];
	va_list			va;
	int len;
	
	va_start(va, format);
	
	// limit the written size and reserve one byte for NULL character
	len = vsnprintf(szBuffer, sizeof(szBuffer) - 1, format, va);
	va_end(va);
	
	if (-1 == len)
	{
		// the string is truncated because of lacking memory
		len = sizeof(szBuffer) -1;
	}
	szBuffer[len] = '\0';

	if(pfDebug)
		pfDebug(MW_DEBUG_ERROR, szBuffer);
}
void mwOsSleep(int  ticks)
{
	UPI_os_thread_sleep(ticks);
}

#if 0
dvb_handle_t mwOsCreateMessage(unsigned int MaxMsgNum, unsigned int MaxMsgRecLen)
{
	dvb_handle_t mHandle;
	
	UPI_os_queue_create(&mHandle ,MaxMsgNum,MaxMsgRecLen);

	return mHandle;
}

int mwOsDeleteMessage(dvb_handle_t msgqhandle)
{
	int ret;
	
	ret = UPI_os_queue_destroy(msgqhandle);
	
	return ret;
}

int mwOsSendMessage(dvb_handle_t msgqhandle,void * msg,int len,int timeout)
{
	int ret;
	
	ret=UPI_os_queue_send(msgqhandle, msg, len);
	if(0!=ret)
	{
		//mwDebug("[SI] mwOsSendMessage %d fail\r\n",ret);
	}

	return ret;
}

int mwOsReceiveMessage(dvb_handle_t msgqhandle,void *msg,int len,int timeout)
{
	int ret;
	int pCount;

	if(timeout ==-1)
	{
		ret =UPI_os_queue_receive(msgqhandle, msg, len, &pCount);
	}
	else
	{
		ret = UPI_os_queue_timed_receive(msgqhandle, msg, len, &pCount, timeout);
	}
	
	if(0!=ret)
	{
		//mwDebug("[SI] mwOsReceiveMessage %d fail\r\n",ret);
	}	
	return ret;
}

int  mwOsEmptyMessage(dvb_handle_t msgqhandle)
{
	int ret;
	
	ret = UPI_os_queue_clear(msgqhandle);

	return ret;
}
#else

typedef struct PDMsgQ
{
	dvb_handle_t  semData; 		/* ¶ÓÁÐÏûÏ¢ÊýÁ¿*/
	dvb_handle_t  semMute;

	unsigned int MaxMsgNum;			/*×îŽóÏûÏ¢ÊýÁ¿*/
	unsigned int MaxMsgRecLen;		/*Ã¿ÌõÏûÏ¢×îŽó³€¶È*/
	unsigned int MsgNum;					/*µ±Ç°ÔÚÏûÏ¢¶ÓÁÐÖÐµÄÏûÏ¢ÊýÁ¿*/

	unsigned int SendPtr;					/*ËÍÈëÏûÏ¢¶ÓÁÐµÄŽæ·ÅÖžÕë*/
	unsigned int RecvPtr; 					//

	unsigned char *msgPool;					/*ÊýŸÝ»º³åÇø*/
}*PRMSGQ;
/******************************************************************************

******************************************************************************/
dvb_handle_t mwOsCreateMessage(unsigned int MaxMsgNum, unsigned int MaxMsgRecLen)
{
	PRMSGQ q;

	q = (PRMSGQ)mwOsAllocMemory(sizeof(struct PDMsgQ));
	if (q == NULL)	return (dvb_handle_t)NULL;

	q->MaxMsgNum = MaxMsgNum;
	q->MaxMsgRecLen = MaxMsgRecLen;

	q->msgPool= mwOsAllocMemory(q->MaxMsgRecLen*q->MaxMsgNum);
	if (q->msgPool == NULL)
	{
		mwOsFreeMemory(q);
		return (dvb_handle_t)NULL;
	}
	
	q->semData = mwOsCreateSemaphore(0);
	if (!q->semData)
	{
		mwDebug("mwOsCreateMessage sem_init failed 1\n");
		mwOsFreeMemory(q->msgPool);
		mwOsFreeMemory(q);
		return (dvb_handle_t)NULL;
	}

	q->semMute = mwOsCreateSemaphore(1);
	if (!q->semMute)
	{
		mwOsDeleteSemaphore(q->semMute);
		mwDebug("mwOsCreateMessage sem_init failed 2\n");
		mwOsFreeMemory(q->msgPool);
		mwOsFreeMemory(q);
		return (dvb_handle_t)NULL;
	}
	
	q->SendPtr = 0;
	q->RecvPtr = 0;
	q->MsgNum=0;
	mwDebug("[OS] mwOsCreateMessage queueID=0x%x,MaxMsgNum=%d,MaxMsgRecLen=%d\n",q,MaxMsgNum,MaxMsgRecLen);
	return (dvb_handle_t)q;

	mwOsFreeMemory(q);
	return (dvb_handle_t)NULL;

}
/******************************************************************************

******************************************************************************/
int mwOsDeleteMessage(dvb_handle_t msgqhandle)
{
	PRMSGQ q=(PRMSGQ)msgqhandle;

	if (!q)
		return -1;

	mwOsFreeMemory(q->msgPool);
	mwOsDeleteSemaphore(q->semData);
	mwOsDeleteSemaphore(q->semMute);
	mwOsFreeMemory(q);
	return 0;
}

/******************************************************************************
timeout-not valid for this version
******************************************************************************/
int mwOsSendMessage(dvb_handle_t msgqhandle, void * msg, int len, int timeout)
{
	PRMSGQ q=(PRMSGQ)msgqhandle;
	int ret;
	unsigned int copylen;

	if(timeout < 0)
		timeout = 0x7FFFFFFF;
	
	if (!q || !msg || !len)
		return -1;
	mwOsWaitSemaphore(q->semMute, -1);
	if(q->MsgNum < q->MaxMsgNum)
	{
		if((unsigned int)len>q->MaxMsgRecLen)
			copylen = q->MaxMsgRecLen;
		else
			copylen = (unsigned int)len;
			
		memcpy(q->msgPool+q->SendPtr*q->MaxMsgRecLen, msg, copylen);
		q->SendPtr=(q->SendPtr+1)%q->MaxMsgNum;				/*·¢ËÍÖžÕëŒÓ1*/
		q->MsgNum++;
		ret = 0;
		mwOsSignalSemaphore(q->semData);							/*±íÊŸ¶ÔÁÐÖÐÒÑÓÐÊýŸÝ,¿ÉÒÔœÓÊÕÁË*/
	}
	else
	{
		mwDebug("mwOsSendMessage message overflow, queueID=0x%x, q->MaxMsgNum = %d\r\n", q, q->MaxMsgNum);
		ret = -1;
	}
	mwOsSignalSemaphore(q->semMute);
	
	return ret;
}
/******************************************************************************
Ê×ÏÈÒªÅÐ¶ÏÓÐÎÞÏûÏ¢
******************************************************************************/
int mwOsReceiveMessage(dvb_handle_t msgqhandle,void *msg,int len,int timeout)
{
	PRMSGQ q=(PRMSGQ)msgqhandle;
	int ret;
	unsigned int copylen;

	if (!q || !msg || !len)
		return -1;

	if(timeout < 0)
		timeout = 0x7FFFFFFF;

	ret = mwOsWaitSemaphore(q->semData, timeout);		/*µÈŽýÊÇ·ñÓÐÊýŸÝ*/
	if (ret==0)
	{
		if (msg)
		{
			mwOsWaitSemaphore(q->semMute, -1);
			if (q->MsgNum >0)				/*ÓÐÏûÏ¢*/
			{
				if((unsigned int)len>q->MaxMsgRecLen)
					copylen = q->MaxMsgRecLen;
				else
					copylen = (unsigned int)len;
				
				memcpy(msg, q->msgPool+q->RecvPtr*q->MaxMsgRecLen,copylen);
				q->RecvPtr=(q->RecvPtr+1)%q->MaxMsgNum;
				q->MsgNum--;
				ret = 0;
			}
			else
			{
				mwDebug("mwOsReceiveMessage error\r\n");
				ret = -1;
			}
			mwOsSignalSemaphore(q->semMute);
		}
	}
	//if(q->MsgNum>0)
	//	mwDebug("[mwOsReceiveMessage] : Why\n");
	
	return ret;
}
/******************************************************************************

******************************************************************************/
 int  mwOsEmptyMessage(dvb_handle_t msgqhandle)
{
	PRMSGQ q=(PRMSGQ)msgqhandle;

	if (q==NULL)
		return -1;

	mwOsWaitSemaphore(q->semMute, -1);
	q->SendPtr = 0;
	q->RecvPtr = 0;
	q->MsgNum=0;
	mwOsSignalSemaphore(q->semMute);

	return 0;
}
#endif

dvb_handle_t  mwOsCreateSemaphore(unsigned int value)
{
	UPI_OsSemHandle semHandle;
	UPI_os_semaphore_create(&semHandle, value);

	return (dvb_handle_t)semHandle;
}

int mwOsDeleteSemaphore (dvb_handle_t semaphore)
{
	int ret;
	
	ret = UPI_os_semaphore_destroy(&semaphore);

	return ret;
}

int mwOsWaitSemaphore(dvb_handle_t semaphore,unsigned int timeout)
{
	int ret;
	
	ret = UPI_os_semaphore_timed_wait(semaphore, timeout);

	return ret;
}

int mwOsSignalSemaphore (dvb_handle_t semaphore)
{
	int ret;
	
	ret = UPI_os_semaphore_post(semaphore);
	
	return ret;
}

unsigned int mwOsGetTickCount(void)
{
	unsigned int tick;//100 ticks = 1s
	tick = UPI_os_current_ticktime();
	return tick;
}
int mwOsCreateTask(unsigned char *name, int prio, int stacksize, unsigned long *id, int mode, task_entry_t func, void *param )
{
	int ret;
	ret = UPI_os_thread_create((void *)func, param, stacksize, prio, name, id, 0);
	return ret;
}

int mwOsTaskDestroy(dvb_handle_t taskid)
{
	int ret;
	ret = UPI_os_thread_destroy(taskid);
	return ret;
}
dvb_handle_t mwOsMutexCreate(char *name)
{
	dvb_handle_t mutexHandle;
	UPI_os_mutex_create(&mutexHandle);
	return mutexHandle;
}

 int mwOsMutexLock(dvb_handle_t hMutex)
{
	int ret;
	ret = UPI_os_mutex_lock(hMutex);
	return ret;
}

 int mwOsMutexUnlock(dvb_handle_t hMutex)
{
	int ret;
	ret = UPI_os_mutex_unlock(hMutex);
	return ret;
}

int mwOsMutexDestroy(dvb_handle_t hMutex)
{
	int ret;
	ret = UPI_os_mutex_destroy(hMutex);
	return ret;
}
void *mwOsAllocMemory(int size)
{
	void *p;
	p = (void *)UPI_os_malloc(size);
	return p;
}
void mwOsFreeMemory( void *p)
{
	int ret;
	_UPI_os_free(p);
	return;
}

//tuner api
dvb_tuner_t curTunerInfo = {0};
unsigned char u8TunerStandby = 0;
unsigned int u32DemoTunerNum = 0;
dvb_demo_param_t* pstDemoTunerList = NULL;

int mwTunerReset(int ReOpenflag)
{
	int ret =0;
	
	mwOsMutexLock(m_tunerMutex);
	if(u8TunerStandby == 1)
	{
		u8TunerStandby = 0;
		if(u32DemoTunerNum == 0)
		{
			ret = cisas_reset_tuner();
		}
		else // demo mode
		{
			//nothing to do
			ret = 0;
		}
		memset(&curTunerInfo, 0, sizeof(curTunerInfo));
	}
	mwOsMutexUnlock(m_tunerMutex);
	
	return ret;
}

int mwTunerLock(dvb_tuner_t * pTUNERINFO, unsigned int u32Force)
{
	int ret =-1;
	unsigned int i;

	mwOsMutexLock(m_tunerMutex);
	if(u8TunerStandby == 1)
	{
		mwError("mwTunerLock() - found tuner standby\r\n");
		mwOsMutexUnlock(m_tunerMutex);
		return -1;
	}
	
	if(curTunerInfo.frequency==pTUNERINFO->frequency && curTunerInfo.symbol_rate==pTUNERINFO->symbol_rate
		&& curTunerInfo.modulation==pTUNERINFO->modulation && u32Force==0)
	{
		mwOsMutexUnlock(m_tunerMutex);
		return 0;
	}
	memcpy(&curTunerInfo, pTUNERINFO, sizeof(curTunerInfo));
	
	if(u32DemoTunerNum == 0)
	{
		ret = cisas_tuner_lock(*pTUNERINFO);
	}
	else // demo mode
	{
		mwDebug("mwTunerLock() - lock %d MHz\r\n", curTunerInfo.frequency);
		//set path to filter module
		for(i=0; i<u32DemoTunerNum; i++)
		{
			if(curTunerInfo.frequency==pstDemoTunerList[i].m_u32Freq && curTunerInfo.modulation==pstDemoTunerList[i].m_u32Mod
				&& curTunerInfo.symbol_rate==pstDemoTunerList[i].m_u32Sym && curTunerInfo.bandwidth==pstDemoTunerList[i].m_u32Bandwidth
				&& curTunerInfo.tunertype==pstDemoTunerList[i].m_eTunerType)
			{
				Filter_SetReadTsFromLocalFile(pstDemoTunerList[i].m_as8Path, pstDemoTunerList[i].m_u32Bitrate);
				break;
			}
		}
		ret = 0;
	}
	
	mwOsMutexUnlock(m_tunerMutex);

	return ret;
}

int mwTunerRelock()
{
	int ret =-1;

	mwOsMutexLock(m_tunerMutex);
	if(u8TunerStandby == 1)
	{
		mwOsMutexUnlock(m_tunerMutex);
		return -1;
	}
	
	if(curTunerInfo.frequency==0 && curTunerInfo.symbol_rate==0)
	{
		mwOsMutexUnlock(m_tunerMutex);
		return -1;
	}
	if(u32DemoTunerNum == 0)
	{
		ret = cisas_tuner_lock(curTunerInfo);
	}
	else // demo mode
	{
		//nothing to do
		ret = 0;
	}
	mwOsMutexUnlock(m_tunerMutex);

	return ret;
}

int mwTunerCurFreq(dvb_tuner_t * pTUNERINFO)
{
	int ret=0;

	mwOsMutexLock(m_tunerMutex);
	memcpy(pTUNERINFO, &curTunerInfo, sizeof(curTunerInfo));
	mwOsMutexUnlock(m_tunerMutex);

	return ret;
}

int mwTunerGetStatus(dvb_tuner_status_t *status)
{
	int ret=1;
	unsigned int i;

	memset(status, 0, sizeof(dvb_tuner_status_t));
	mwOsMutexLock(m_tunerMutex);
	if(u8TunerStandby == 1)
	{
		mwOsMutexUnlock(m_tunerMutex);
		return -1;
	}
	if(u32DemoTunerNum == 0)
	{
		ret = cisas_get_tuner_status(status);
	}
	else // demo mode
	{
		//found tuner 
		for(i=0; i<u32DemoTunerNum; i++)
		{
			if(curTunerInfo.frequency==pstDemoTunerList[i].m_u32Freq 
				&& curTunerInfo.modulation==pstDemoTunerList[i].m_u32Mod
				&& curTunerInfo.symbol_rate==pstDemoTunerList[i].m_u32Sym
				&& curTunerInfo.bandwidth==pstDemoTunerList[i].m_u32Bandwidth
				&& curTunerInfo.tunertype==pstDemoTunerList[i].m_eTunerType)
			{
				mwDebug("mwTunerGetStatus() - lock %d MHz OK\r\n", curTunerInfo.frequency);
				status->frequency = curTunerInfo.frequency;
				status->modulation = curTunerInfo.modulation;
				status->symbol_rate = curTunerInfo.symbol_rate;
				status->bandwidth = curTunerInfo.bandwidth;
				status->bLock = 1;
				status->level = 60;
				status->snr = 95;
				break;
			}
		}
		ret = 0;
		
		if(i >= u32DemoTunerNum)//not found
		{
			mwDebug("mwTunerGetStatus() - lock %d MHz not OK\r\n", curTunerInfo.frequency);
			status->frequency = curTunerInfo.frequency;
			status->modulation = curTunerInfo.modulation;
			status->symbol_rate = curTunerInfo.symbol_rate;
			status->bandwidth = curTunerInfo.bandwidth;
			status->bLock = 0;
			status->level = 0;
			status->snr = 0;
		}
		
	}
	mwOsMutexUnlock(m_tunerMutex);
	
	return ret;
}

//Atomic check and relock
//return: 	0 - 	check ok
//			1 - 	check not ok, relock ok
//			-1-	all not ok
int mwTunerCheckAndRelock(unsigned char* pu8IsLock)
{
	int ret = -1;
	dvb_tuner_status_t Tunerstatus;
	static unsigned char u8UnlockTime = 0;
	unsigned int i;

	*pu8IsLock = 0;
	mwOsMutexLock(m_tunerMutex);
	if(u8TunerStandby == 1)
	{
		mwOsMutexUnlock(m_tunerMutex);
		return -1;
	}

	if(u32DemoTunerNum == 0)
	{
		ret = cisas_get_tuner_status(&Tunerstatus);
		if(ret == 0)
		{
			if(Tunerstatus.frequency!=curTunerInfo.frequency/* || Tunerstatus.modulation!=curTunerInfo.modulation
							|| Tunerstatus.symbol_rate != curTunerInfo.symbol_rate*/)
			{
				mwDebug("mwTunerCheckAndRelock relock tuner for ci sas session not open\r\n");
				ret = cisas_tuner_lock(curTunerInfo);
				if(ret == 0)
				{
					ret = 1;//relock ok
				}
				*pu8IsLock = 0;
			}
			else
			{
				if(Tunerstatus.bLock == 0)
				{
					u8UnlockTime++;
					if(u8UnlockTime >= 2)
					{
						*pu8IsLock = Tunerstatus.bLock;
						if(Tunerstatus.bLock == 0 || Tunerstatus.snr<23)
						{
							mwDebug("mwTunerCheckAndRelock relock for snc < 23 or not lock\r\n");
							cisas_tuner_lock(curTunerInfo);
						}
					}
					else
					{
						mwDebug("mwTunerCheckAndRelock() -  unlock, but times not enough\r\n");
						Tunerstatus.bLock = 1;
						*pu8IsLock = Tunerstatus.bLock;
					}
				}
				else
				{
					u8UnlockTime = 0;
					*pu8IsLock = Tunerstatus.bLock;
				}
			}
		}
	}
	else
	{
		ret = 0;
		for(i=0; i<u32DemoTunerNum; i++)
		{
			if(curTunerInfo.frequency==pstDemoTunerList[i].m_u32Freq 
				&& curTunerInfo.modulation==pstDemoTunerList[i].m_u32Mod
				&& curTunerInfo.symbol_rate==pstDemoTunerList[i].m_u32Sym
				&& curTunerInfo.bandwidth==pstDemoTunerList[i].m_u32Bandwidth
				&& curTunerInfo.tunertype==pstDemoTunerList[i].m_eTunerType)
			{
				*pu8IsLock = 1;
				break;
			}
		}
		mwDebug("mwTunerCheckAndRelock local file return lock status %d, curTunerInfo.frequency = %d\r\n", 
			*pu8IsLock, curTunerInfo.frequency);
	}
	mwOsMutexUnlock(m_tunerMutex);
	return ret;
}

int mwTunerStandby()
{
	int ret=1;

	mwOsMutexLock(m_tunerMutex);
	u8TunerStandby = 1;
	if(u32DemoTunerNum == 0)
	{
		ret = cisas_tuner_standby();
	}
	else // demo mode
	{
		ret = Filter_SetReadTsFromLocalFile(NULL, 0);
	}
	mwOsMutexUnlock(m_tunerMutex);
	
	return ret;
}

int mwTunerResume()
{
	int ret;

	mwOsMutexLock(m_tunerMutex);
	u8TunerStandby = 0;
	if(u32DemoTunerNum == 0)
	{
		ret = cisas_tuner_resume();
	}
	else // demo mode
	{
		ret = 0;
	}
	mwOsMutexUnlock(m_tunerMutex);
	
	return ret;
}

int mwTunerDemoModeSetParam(dvb_demo_param_t* pstParam, unsigned int u32Num)
{
	int s32Ret = -1;
	int i;

	mwOsMutexLock(m_tunerMutex);
	u32DemoTunerNum = u32Num;
	if(u32DemoTunerNum > 0)
	{
		if(pstParam != NULL)
		{
			if(pstDemoTunerList)
				mwOsFreeMemory(pstDemoTunerList);
			pstDemoTunerList = mwOsAllocMemory(sizeof(dvb_demo_param_t)*u32Num);
			if(pstDemoTunerList)
			{
				memcpy(pstDemoTunerList, pstParam, sizeof(dvb_demo_param_t)*u32Num);
				s32Ret = cisas_tuner_standby();

				//set path to filter
				for(i=0; i<u32DemoTunerNum; i++)
				{
					if(curTunerInfo.frequency==pstDemoTunerList[i].m_u32Freq && curTunerInfo.modulation==pstDemoTunerList[i].m_u32Mod
						&& curTunerInfo.symbol_rate==pstDemoTunerList[i].m_u32Sym && curTunerInfo.bandwidth==pstDemoTunerList[i].m_u32Bandwidth
						&& curTunerInfo.tunertype==pstDemoTunerList[i].m_eTunerType)
					{
						Filter_SetReadTsFromLocalFile(pstDemoTunerList[i].m_as8Path, pstDemoTunerList[i].m_u32Bitrate);
					}
				}
			}
			else
			{
				u32DemoTunerNum = 0;
			}
		}
		else
		{
			u32DemoTunerNum = 0;
		}
	}
	else
	{
		s32Ret = cisas_tuner_resume();
		Filter_SetReadTsFromLocalFile(NULL, 0);
	}
	mwOsMutexUnlock(m_tunerMutex);
	
	return s32Ret;
}

//dmx api
int mwSectionDataGot( filter_handle_t hFilter,  unsigned char* pu8Data,  unsigned short u16Datalen)
{
	int ret =0;
	unsigned int i;

	if(hFilter == INVALID_FILTER_HANDLE)
	{
		mwDebug("mwSectionDataGot receive error hFilter\r\n");
		return -1;
	}
	
	mwOsMutexLock(m_mutex);
	for(i=0; i<sizeof(s_ahFilter)/sizeof(s_ahFilter[0]); i++)
	{
		if(s_ahFilter[i].m_hFilter == hFilter)
			break;
	}

	if(i < sizeof(s_ahFilter)/sizeof(s_ahFilter[0]))
	{
		if(s_ahFilter[i].m_hQueueID != (dvb_handle_t)NULL)
			mwOsSendMessage(s_ahFilter[i].m_hQueueID, pu8Data, u16Datalen, 0);
		else if(s_ahFilter[i].m_pfCallback)
			s_ahFilter[i].m_pfCallback(s_ahFilter[i].m_hFilter, pu8Data, u16Datalen);
		else
			mwDebug("mwSectionDataGot found no notify hFilter = %x\r\n", hFilter);
	}
	else
	{
		mwDebug("mwSectionDataGot found no slot hFilter = %x\r\n", hFilter);
		ret = -1;
	}
	mwOsMutexUnlock(m_mutex);

	return ret;
}


int mwDmxStartFilter(filter_param_t* pParam, dvb_handle_t *hfilter)
{
	int ret =0;
	filter_section_param_t stSecParam;
	unsigned int i;

	stSecParam.m_u16Pid = pParam->m_u16Pid;
	stSecParam.m_u8CrcCheck = pParam->m_u8CrcCheck;
	stSecParam.m_u8FilterDepth = pParam->m_u8FilterDepth;
	stSecParam.m_pu16SectByte = pParam->m_pu16SectByte;
	stSecParam.m_pfCallback = mwSectionDataGot;

	mwOsMutexLock(m_mutex);
	for(i=0; i<sizeof(s_ahFilter)/sizeof(s_ahFilter[0]); i++)
	{
		if(s_ahFilter[i].m_hFilter == INVALID_FILTER_HANDLE)
			break;
	}
	if(i < sizeof(s_ahFilter)/sizeof(s_ahFilter[0]))
	{
		s_ahFilter[i].m_hQueueID = pParam->m_hQueueID;
		s_ahFilter[i].m_pfCallback = pParam->m_pfCb;
		Filter_StartSectionFilter(&stSecParam, &s_ahFilter[i].m_hFilter);
		*hfilter = s_ahFilter[i].m_hFilter;
		if(s_ahFilter[i].m_hFilter == INVALID_FILTER_HANDLE)
		{
			ret = -1;
		}
	}
	else
	{
		mwDebug("mwDmxStartFilter found no free slot\r\n");
		ret = -1;
	}
	mwOsMutexUnlock(m_mutex);
	
	return ret;
}

int mwDmxStopFilter(dvb_handle_t hfilter)
{
	int ret = 0;
	unsigned int i;

	if(hfilter == INVALID_FILTER_HANDLE)
		return -1;
	
	mwOsMutexLock(m_mutex);
	for(i=0; i<sizeof(s_ahFilter)/sizeof(s_ahFilter[0]); i++)
	{
		if(s_ahFilter[i].m_hFilter == hfilter)
			break;
	}

	if(i < sizeof(s_ahFilter)/sizeof(s_ahFilter[0]))
	{
		Filter_StopSectionFilter(s_ahFilter[i].m_hFilter);
		s_ahFilter[i].m_hFilter = INVALID_FILTER_HANDLE;
	}
	else
	{
		ret = -1;
	}
	mwOsMutexUnlock(m_mutex);
	
	return ret;
}

int mwDmxEnableFilter(dvb_handle_t handle)
{
	int ret;
	return ret;
}

int mwDmxDisableFilter(dvb_handle_t handle)
{
	int ret;
	return ret;
}
int  mwNvmRead(FLASH_ID readId, unsigned int Offset, unsigned char *targetData,  int numBytes)
{
	int ret;
	FILE* fd = NULL;
	mwOsMutexLock(m_mutex);
	if(0 != access(savedir,F_OK))
	{
		mkdir(savedir,0776);
	}
	fd = fopen(savefile, "rb+");
	if (fd == NULL)
	{
		mwError("mwNvmRead error, can not open the file /data/nand/FLASH4M.hex,%d,%s",fd,strerror(errno));
		mwOsMutexUnlock(m_mutex);		
		return -1;
	}

	switch(readId)
	{
		case FLASH_USER_CONFIG:
			Offset += 0;
			break;
		case FLASH_USER_CONFIG_BK:
			Offset += 0x10000;
			break;
		case FLASH_BOOKING:
			Offset += 0x20000;
			break;
		case FLASH_CURSERVICE:
			Offset += 0x30000;
			break;
		case FLASH_SIDATA:
			Offset += 0x40000;
			break;
		default:
			fclose(fd);
			mwOsMutexUnlock(m_mutex);		
			return -1;
	}

	
	ret=fseek(fd,Offset,SEEK_SET);
	if(ret != 0)
	{
		mwError("mwNvmRead error, can not SEEK_SET the file /data/nand/FLASH4M.hex,%d,%s",fd,strerror(errno));
	}
	ret=fread(targetData, 1, numBytes, fd);
	fclose(fd);
	fd=NULL;
	mwOsMutexUnlock(m_mutex);

	return ret;
}

int  mwNvmWrite(FLASH_ID writeId, unsigned int Offset, unsigned char *sourceData,  int numBytes)
{
	int num;
	FILE* fd = NULL;
	

	mwOsMutexLock(m_mutex);

	if(0 != access(savedir,F_OK))
	{
		mkdir(savedir,0776);
	}
	
	if(0 != access(savefile,F_OK))
	{
		fd  = fopen(savefile,"w");
	}
	else
	{
		fd = fopen(savefile, "rb+");
	}

	if (fd == NULL)		
	{
		mwError("mwNvmWrite error, can not open the file /data/nand/FLASH4M.hex,%d,%s",fd,strerror(errno));
		mwOsMutexUnlock(m_mutex);		
		return -1;
	}

	switch(writeId)
	{
		case FLASH_USER_CONFIG:
			Offset += 0;
			break;
		case FLASH_USER_CONFIG_BK:
			Offset += 0x10000;
			break;
		case FLASH_BOOKING:
			Offset += 0x20000;
			break;
		case FLASH_CURSERVICE:
			Offset += 0x30000;
			break;
		case FLASH_SIDATA:
			Offset += 0x40000;
			break;
		default:
			fclose(fd);
			mwOsMutexUnlock(m_mutex);			
			return -1;
	}
	
	num=fseek(fd,Offset,SEEK_SET);
	if(num != 0)
	{
		mwError("mwNvmWrite error, can not SEEK_SET the file /data/nand/FLASH4M.hex,%d,%s",fd,strerror(errno));
	}
	num=fwrite(sourceData,1, numBytes,fd);
	sync();
	fclose(fd);
	fd=NULL;
	if (num <=0)
	{
		mwError("mwNvmWrite error, write data error!!");
		mwOsMutexUnlock(m_mutex);		
		return -1;
	}	
	mwOsMutexUnlock(m_mutex);	

	return 0;
}


int mwAvPlay(int hplay, unsigned short pmtPID, unsigned short serID, unsigned short pcrPID, unsigned short vidPID, unsigned short vidType, unsigned short audPID, unsigned short audType)
{
	int ret = 0;
	spts_param_t* pstSptsParam;

	mwDebug("mwAvPlay entry, pmtPID = %d, serID = %d, pcrPid = %d, vidPID = %d, vidType = %d, audPID = %d, audType = %d\r\n",
		pmtPID, serID, pcrPID, vidPID, vidType, audPID, audType);
	pstSptsParam = (spts_param_t*)mwOsAllocMemory(sizeof(spts_param_t)+sizeof(spts_es_t)*2);
	if(pstSptsParam)
	{
		SPTS_OutputStop();
		pstSptsParam->m_u16ServiceId = serID;
		pstSptsParam->m_u16PcrPid = pcrPID;
		pstSptsParam->m_u16PmtPid = pmtPID;
		pstSptsParam->m_u16EsCnt = 2;
		pstSptsParam->m_astEs[0].m_u32Type = vidType;
		pstSptsParam->m_astEs[0].m_u16Pid = vidPID;
		if(vidPID == 0)
		{
			pstSptsParam->m_astEs[0].m_u16Pid = 0x1fff;
			vidPID = 0x1fff;
		}
		pstSptsParam->m_astEs[1].m_u32Type = audType;
		pstSptsParam->m_astEs[1].m_u16Pid = audPID;
		if(audPID == 0)
		{
			pstSptsParam->m_astEs[1].m_u16Pid = 0x1fff;
			audPID = 0x1fff;
		}
		SPTS_OutputSet(pstSptsParam);
		SPTS_OutputStart();
		mwOsFreeMemory(pstSptsParam);

		if(hplay == 0)
		{
			ret = DVBDecoderStop();
			if(ret != 0)
				mwDebug("mwAvPlay() - DVBDecoderStop ret = %d\r\n", ret);
			ret = DVBDecoderSetParam(pcrPID, vidPID, vidType, audPID, audType);
			if(ret != 0)
				mwDebug("mwAvPlay() - DVBDecoderSetParam ret = %d\r\n", ret);
			ret = DVBDecoderStart();
			if(ret != 0)
				mwDebug("mwAvPlay() - DVBDecoderStart ret = %d\r\n", ret);
		}
		
	}
	else
		ret = -1;
	return ret;
}

int mwAvStop(int hplay)
{
	int ret;

	mwDebug("mwAvStop - entry.\r\n");
	cas_stop_discrambling();
	ret = SPTS_OutputStop();
	if(hplay == 0)
	{
		ret = DVBDecoderStop();
		if(ret != 0)
			mwDebug("mwAvStop() - DVBDecoderStop ret = %d\r\n", ret);
		ret = DVBDecoderClearVideo();
		if(ret != 0)
			mwDebug("mwAvStop() - DVBDecoderClearVideo ret = %d\r\n", ret);
		ret = DVBDecoderDeinit();
		if(ret != 0)
			mwDebug("mwAvStop DVBDecoder ret = %d\r\n", ret);
	}	
	mwDebug("mwAvStop - return.\r\n");
	return ret;
}

int mwAvBlackScreen()
{
	int ret = 0;

	ret = DVBDecoderClearVideo();
	if(ret != 0)
		mwDebug("mwAvBlackScreen DVBDecoderClearVideo ret = %d\r\n", ret);

	return ret;
}

int mwAvSetStereoMode (STEREOMODE mode)
{
	return mode;
}

int mwAvSetVolume(int vol)
{
	return vol;
}

int mwAvSwitchAudio(unsigned short audPID, unsigned short audType)
{
	return 0;
}

int mwAvGetPlayStatus(DECODER_STATUS* peStatus)
{
	int rc = 0;
	spts_status_t eStats = DECODER_STATUS_NOT_PLAYING;
	
	if(peStatus)
	{
		rc = SPTS_GetOutputStatus(&eStats);
		switch(eStats)
		{
			case SPTS_OUTPUT_VIDEO_OK:
				*peStatus = DECODER_STATUS_VIDEO_PLAYING;
				break;
			case SPTS_OUTPUT_AUDIO_OK:
				*peStatus = DECODER_STATUS_AUDIO_PLAYING;
				break;
			case SPTS_OUTPUT_ALL_ES_OK:
				*peStatus = DECODER_STATUS_AV_PLAYING;
				break;
			case SPTS_OUTPUT_NONE:
				*peStatus = DECODER_STATUS_NOT_PLAYING;
				break;
			default:
				*peStatus = DECODER_STATUS_NOT_PLAYING;
				break;
		}
	}
	return rc;
}

int mwAvGetScrambleStatus(DECODER_SCRAMBLE_STATUS* peStatus)
{
	int rc = 0;
	spts_scramble_status_t eStats = SPTS_ENCRYTION_UNKNOWED;
	
	if(peStatus)
	{
		rc = SPTS_GetScrambleStatus(&eStats);
		switch(eStats)
		{
			case SPTS_ENCRYTION_UNKNOWED:
				*peStatus = DECODER_STATUS_SCRAMBLE_UNKNOWN;
				break;
			case SPTS_ENCRYTION_FREE:
				*peStatus = DECODER_STATUS_AV_FREE;
				break;
			case SPTS_ENCRYTION_VIDEO_SRCAMBLE:
				*peStatus = DECODER_STATUS_AUDIO_FREE;
				break;
			case SPTS_ENCRYTION_AUDIO_SCRAMBLE:
				*peStatus = DECODER_STATUS_VIDEO_FREE;
				break;
			case SPTS_ENCRYTION_SCRAMBLE:
				*peStatus = DECODER_STATUS_AV_SCRAMBLE;
				break;
			default:
				*peStatus = DECODER_STATUS_SCRAMBLE_UNKNOWN;
				break;
		}
	}
	return rc;
}

int mwCIStartDescrable(unsigned char* pu8Pmt, unsigned short u16Len)
{
	mwDebug(" [%s  %d]\n",__FUNCTION__,__LINE__);
	cas_send_program_pmt(0, pu8Pmt, u16Len);
	return 0;
}

void* mwDLOpen(char* ps8Path)
{
	void* handle;
	
	handle = dlopen(ps8Path, RTLD_LAZY);

	return handle;
}

void* mwDLLoadSymbol(void* phFile, char* ps8FuncName)
{
	void* handle = NULL;
	
	handle = dlsym(phFile, ps8FuncName);

	return handle;
}

void mwDLClose(void* phFile)
{
	dlclose(phFile);
}

